Iteration with purrr

R4DS 17 - purrr

lruolin
05-27-2021

R4DS Practice 17: Iteration with purrr

The codes below are from the practice exercises in https://r4ds.had.co.nz/, and are taken with reference from: https://jrnold.github.io/r4ds-exercise-solutions/

Let’s begin now

Loading tidyverse package.

For Loops

df <- tibble(
  a = rnorm(10),
  b = rnorm(10),
  c = rnorm(10),
  d = rnorm(10)
)

# to compute the median of each column:

median(df$a)
[1] 0.2939953
median(df$b)
[1] -0.6834013
# use a for loop:

output <- vector("double", ncol(df))

  for(i in seq_along(df)) {  # df[[1]] , df[[2]], df[[3]], df[[4]]
  
  output[[i]] <-  median(df[[i]])
  
}

output
[1]  0.2939953 -0.6834013 -0.3643358  0.3220519

Write for loops to compute the mean of every column in mtcars

# to compute the mean for every column in mtcars:

glimpse(mtcars)
Rows: 32
Columns: 11
$ mpg  <dbl> 21.0, 21.0, 22.8, 21.4, 18.7, 18.1, 14.3, 24.4, 22.8, 1…
$ cyl  <dbl> 6, 6, 4, 6, 8, 6, 8, 4, 4, 6, 6, 8, 8, 8, 8, 8, 8, 4, 4…
$ disp <dbl> 160.0, 160.0, 108.0, 258.0, 360.0, 225.0, 360.0, 146.7,…
$ hp   <dbl> 110, 110, 93, 110, 175, 105, 245, 62, 95, 123, 123, 180…
$ drat <dbl> 3.90, 3.90, 3.85, 3.08, 3.15, 2.76, 3.21, 3.69, 3.92, 3…
$ wt   <dbl> 2.620, 2.875, 2.320, 3.215, 3.440, 3.460, 3.570, 3.190,…
$ qsec <dbl> 16.46, 17.02, 18.61, 19.44, 17.02, 20.22, 15.84, 20.00,…
$ vs   <dbl> 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1…
$ am   <dbl> 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1…
$ gear <dbl> 4, 4, 4, 3, 3, 3, 3, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4…
$ carb <dbl> 4, 4, 1, 1, 2, 1, 4, 2, 2, 4, 4, 3, 3, 3, 4, 4, 4, 1, 2…
mtcars[[1]] # first column
 [1] 21.0 21.0 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 17.8 16.4 17.3
[14] 15.2 10.4 10.4 14.7 32.4 30.4 33.9 21.5 15.5 15.2 13.3 19.2 27.3
[27] 26.0 30.4 15.8 19.7 15.0 21.4
mtcars[[2]] # second column
 [1] 6 6 4 6 8 6 8 4 4 6 6 8 8 8 8 8 8 4 4 4 4 8 8 8 8 4 4 4 8 6 8 4
mean(mtcars[[1]]) # mean  = 20.09062
[1] 20.09062
# for loop

output <-  vector("double", ncol(mtcars))

for (i in seq_along(mtcars))
  output[[i]] <-  mean(mtcars[[i]])

output
 [1]  20.090625   6.187500 230.721875 146.687500   3.596563   3.217250
 [7]  17.848750   0.437500   0.406250   3.687500   2.812500
output <- vector("double", ncol(mtcars))
names(output) <- names(mtcars)
for (i in names(mtcars)) {
  output[i] <- mean(mtcars[[i]])
}
output
       mpg        cyl       disp         hp       drat         wt 
 20.090625   6.187500 230.721875 146.687500   3.596563   3.217250 
      qsec         vs         am       gear       carb 
 17.848750   0.437500   0.406250   3.687500   2.812500 

Write for loops to determine the type of each column in nycflights13::flights

library(nycflights13)
glimpse(flights)
Rows: 336,776
Columns: 19
$ year           <int> 2013, 2013, 2013, 2013, 2013, 2013, 2013, 201…
$ month          <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
$ day            <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
$ dep_time       <int> 517, 533, 542, 544, 554, 554, 555, 557, 557, …
$ sched_dep_time <int> 515, 529, 540, 545, 600, 558, 600, 600, 600, …
$ dep_delay      <dbl> 2, 4, 2, -1, -6, -4, -5, -3, -3, -2, -2, -2, …
$ arr_time       <int> 830, 850, 923, 1004, 812, 740, 913, 709, 838,…
$ sched_arr_time <int> 819, 830, 850, 1022, 837, 728, 854, 723, 846,…
$ arr_delay      <dbl> 11, 20, 33, -18, -25, 12, 19, -14, -8, 8, -2,…
$ carrier        <chr> "UA", "UA", "AA", "B6", "DL", "UA", "B6", "EV…
$ flight         <int> 1545, 1714, 1141, 725, 461, 1696, 507, 5708, …
$ tailnum        <chr> "N14228", "N24211", "N619AA", "N804JB", "N668…
$ origin         <chr> "EWR", "LGA", "JFK", "JFK", "LGA", "EWR", "EW…
$ dest           <chr> "IAH", "IAH", "MIA", "BQN", "ATL", "ORD", "FL…
$ air_time       <dbl> 227, 227, 160, 183, 116, 150, 158, 53, 140, 1…
$ distance       <dbl> 1400, 1416, 1089, 1576, 762, 719, 1065, 229, …
$ hour           <dbl> 5, 5, 5, 5, 6, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, …
$ minute         <dbl> 15, 29, 40, 45, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0…
$ time_hour      <dttm> 2013-01-01 05:00:00, 2013-01-01 05:00:00, 20…
# to find out the class of column:
class(flights$year)
[1] "integer"
class(flights[[1]]) # integer
[1] "integer"
output <- vector("list", ncol(flights)) # output is a list

names(output) <- names(flights) # set name of output

for (i in names(flights)) {
  output[[i]] <- class(flights[[i]])
}
output
$year
[1] "integer"

$month
[1] "integer"

$day
[1] "integer"

$dep_time
[1] "integer"

$sched_dep_time
[1] "integer"

$dep_delay
[1] "numeric"

$arr_time
[1] "integer"

$sched_arr_time
[1] "integer"

$arr_delay
[1] "numeric"

$carrier
[1] "character"

$flight
[1] "integer"

$tailnum
[1] "character"

$origin
[1] "character"

$dest
[1] "character"

$air_time
[1] "numeric"

$distance
[1] "numeric"

$hour
[1] "numeric"

$minute
[1] "numeric"

$time_hour
[1] "POSIXct" "POSIXt" 

Compute the number of unique values in each column of iris

glimpse(iris)
Rows: 150
Columns: 5
$ Sepal.Length <dbl> 5.1, 4.9, 4.7, 4.6, 5.0, 5.4, 4.6, 5.0, 4.4, 4.…
$ Sepal.Width  <dbl> 3.5, 3.0, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9, 3.…
$ Petal.Length <dbl> 1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5, 1.4, 1.…
$ Petal.Width  <dbl> 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.…
$ Species      <fct> setosa, setosa, setosa, setosa, setosa, setosa,…
iris[[1]] # first col of iris: sepal.length
  [1] 5.1 4.9 4.7 4.6 5.0 5.4 4.6 5.0 4.4 4.9 5.4 4.8 4.8 4.3 5.8 5.7
 [17] 5.4 5.1 5.7 5.1 5.4 5.1 4.6 5.1 4.8 5.0 5.0 5.2 5.2 4.7 4.8 5.4
 [33] 5.2 5.5 4.9 5.0 5.5 4.9 4.4 5.1 5.0 4.5 4.4 5.0 5.1 4.8 5.1 4.6
 [49] 5.3 5.0 7.0 6.4 6.9 5.5 6.5 5.7 6.3 4.9 6.6 5.2 5.0 5.9 6.0 6.1
 [65] 5.6 6.7 5.6 5.8 6.2 5.6 5.9 6.1 6.3 6.1 6.4 6.6 6.8 6.7 6.0 5.7
 [81] 5.5 5.5 5.8 6.0 5.4 6.0 6.7 6.3 5.6 5.5 5.5 6.1 5.8 5.0 5.6 5.7
 [97] 5.7 6.2 5.1 5.7 6.3 5.8 7.1 6.3 6.5 7.6 4.9 7.3 6.7 7.2 6.5 6.4
[113] 6.8 5.7 5.8 6.4 6.5 7.7 7.7 6.0 6.9 5.6 7.7 6.3 6.7 7.2 6.2 6.1
[129] 6.4 7.2 7.4 7.9 6.4 6.3 6.1 7.7 6.3 6.4 6.0 6.9 6.7 6.9 5.8 6.8
[145] 6.7 6.7 6.3 6.5 6.2 5.9
n_distinct(iris[[1]]) # number of unique values
[1] 35
iris_unique <- vector("double", ncol(iris)) # vector produces a vector of the given length and mode
names(iris_unique) <-  names(iris) # set the name of vector according to the iris dataset

for(i in names(iris)) {
  iris_unique[i] <- n_distinct(iris[[i]])
}

iris_unique
Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species 
          35           23           43           22            3 

Generate 10 random normals for each of miu = -10, 0, 10 and 100

# generate 10 numbers
n <- 10

# pre-set values for mean

mu <- c(-10, 0, 10, 100)


# write the forloop

normals <- vector("list", length(mu))
for (i in seq_along(normals)) {
  
  normals[[i]] <- rnorm(n, mean = mu[[i]])
}

# this example requires me to create the list myself

For Loop Variations - Modifying an Existing Object

df
# A tibble: 10 x 4
        a      b       c      d
    <dbl>  <dbl>   <dbl>  <dbl>
 1 -0.148 -0.623 -0.767   0.707
 2  1.10  -1.62   0.569   1.27 
 3  2.14  -1.47  -1.03    0.137
 4  0.256  0.193  0.389  -2.11 
 5  1.59  -0.792 -2.03    0.542
 6 -1.41   1.00  -0.628   0.385
 7  0.331 -0.751  0.0282  1.41 
 8 -1.30  -0.744 -1.86    0.259
 9  0.422  0.683 -0.101  -0.325
10  0.257 -0.359  0.692  -0.741
# rescale function

rescale01 <- function(x){
  range <- range(x, na.rm = T)
  (x-range[1] / (range[2] - range[1]))
  
}

rescale01(df$a)
 [1]  0.2491601  1.4979938  2.5344229  0.6530507  1.9901675 -1.0088461
 [7]  0.7271936 -0.9065514  0.8184003  0.6541429
rescale01(df$b)
 [1] -0.005368567 -0.997429229 -0.855877454  0.810609489 -0.173857050
 [6]  1.617268846 -0.133204444 -0.125996565  1.300225157  0.258333590
# to solve this with a for loop,

# output: same as input
# sequence: seq_along(df)
# body: apply rescale01

seq_along(df) # generate sequences
[1] 1 2 3 4
for(i in seq_along(df)) {
  df[[i]] <- rescale01(df[[i]]) # use double square brackets
}

df
# A tibble: 10 x 4
        a        b       c      d
    <dbl>    <dbl>   <dbl>  <dbl>
 1  0.249 -0.00537 -0.0211  1.31 
 2  1.50  -0.997    1.31    1.87 
 3  2.53  -0.856   -0.282   0.737
 4  0.653  0.811    1.14   -1.51 
 5  1.99  -0.174   -1.29    1.14 
 6 -1.01   1.62     0.118   0.984
 7  0.727 -0.133    0.774   2.01 
 8 -0.907 -0.126   -1.11    0.859
 9  0.818  1.30     0.645   0.275
10  0.654  0.258    1.44   -0.141

For Loops vs Functionals

R is a functional programming language, meaning it is possible to wrap up for loops in a function, and call that function instead of using for loop directly.

Solutions that make use of loops are less efficient than vectorized solutions that make use of apply functions, such as lapply and sapply.

There is also more clarity with using map() in purrr, rather than using for loops.

x <- list(a = 1:10,
          beta = exp(-3:3),
          logic = c(T, F, F, T))
x
$a
 [1]  1  2  3  4  5  6  7  8  9 10

$beta
[1]  0.04978707  0.13533528  0.36787944  1.00000000  2.71828183
[6]  7.38905610 20.08553692

$logic
[1]  TRUE FALSE FALSE  TRUE
# lapply returns a list of the same length as x
lapply(x, mean)  # variable, function
$a
[1] 5.5

$beta
[1] 4.535125

$logic
[1] 0.5
# sapply returns a vector by default
sapply(x, quantile)
         a        beta logic
0%    1.00  0.04978707   0.0
25%   3.25  0.25160736   0.0
50%   5.50  1.00000000   0.5
75%   7.75  5.05366896   1.0
100% 10.00 20.08553692   1.0
# use sapply to find missing values
sapply(x, function(x) sum(is.na(x))) # creating an anonymous function
    a  beta logic 
    0     0     0 

Map Functions

The focus is on the operation being performed, not the steps/codes to loop over which element and store as which output. The first argument is always the data object you want to map over, and the second argument is the function that you want to apply.

df
# A tibble: 10 x 4
        a        b       c      d
    <dbl>    <dbl>   <dbl>  <dbl>
 1  0.249 -0.00537 -0.0211  1.31 
 2  1.50  -0.997    1.31    1.87 
 3  2.53  -0.856   -0.282   0.737
 4  0.653  0.811    1.14   -1.51 
 5  1.99  -0.174   -1.29    1.14 
 6 -1.01   1.62     0.118   0.984
 7  0.727 -0.133    0.774   2.01 
 8 -0.907 -0.126   -1.11    0.859
 9  0.818  1.30     0.645   0.275
10  0.654  0.258    1.44   -0.141
# calculate mean for each column in df
map_dbl(df, mean) # df, function
        a         b         c         d 
0.7209134 0.1694704 0.2723914 0.7529901 
map(df, mean) # returns a list
$a
[1] 0.7209134

$b
[1] 0.1694704

$c
[1] 0.2723914

$d
[1] 0.7529901
# calculate median for each column in df
map_dbl(df, median)
          a           b           c           d 
 0.69066825 -0.06568257  0.38151973  0.92170995 
df %>% 
  map_dbl(mean) # calculate mean for each col in df
        a         b         c         d 
0.7209134 0.1694704 0.2723914 0.7529901 

To apply a linear model to each group in a dataset:

models <- mtcars %>% 
  split(.$cyl) %>% # divides the data in the vector into groups
  map( ~lm(mpg ~wt, data = .))

models  
$`4`

Call:
lm(formula = mpg ~ wt, data = .)

Coefficients:
(Intercept)           wt  
     39.571       -5.647  


$`6`

Call:
lm(formula = mpg ~ wt, data = .)

Coefficients:
(Intercept)           wt  
      28.41        -2.78  


$`8`

Call:
lm(formula = mpg ~ wt, data = .)

Coefficients:
(Intercept)           wt  
     23.868       -2.192  
# to extract model summary:

models %>% 
  map(summary) %>% 
  map_dbl("r.squared") # provide the name of the element to extract
        4         6         8 
0.5086326 0.4645102 0.4229655 

Compute the mean of every column in mtcars

glimpse(mtcars)
Rows: 32
Columns: 11
$ mpg  <dbl> 21.0, 21.0, 22.8, 21.4, 18.7, 18.1, 14.3, 24.4, 22.8, 1…
$ cyl  <dbl> 6, 6, 4, 6, 8, 6, 8, 4, 4, 6, 6, 8, 8, 8, 8, 8, 8, 4, 4…
$ disp <dbl> 160.0, 160.0, 108.0, 258.0, 360.0, 225.0, 360.0, 146.7,…
$ hp   <dbl> 110, 110, 93, 110, 175, 105, 245, 62, 95, 123, 123, 180…
$ drat <dbl> 3.90, 3.90, 3.85, 3.08, 3.15, 2.76, 3.21, 3.69, 3.92, 3…
$ wt   <dbl> 2.620, 2.875, 2.320, 3.215, 3.440, 3.460, 3.570, 3.190,…
$ qsec <dbl> 16.46, 17.02, 18.61, 19.44, 17.02, 20.22, 15.84, 20.00,…
$ vs   <dbl> 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1…
$ am   <dbl> 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1…
$ gear <dbl> 4, 4, 4, 3, 3, 3, 3, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4…
$ carb <dbl> 4, 4, 1, 1, 2, 1, 4, 2, 2, 4, 4, 3, 3, 3, 4, 4, 4, 1, 2…
mtcars %>% 
  map_dbl(mean)
       mpg        cyl       disp         hp       drat         wt 
 20.090625   6.187500 230.721875 146.687500   3.596563   3.217250 
      qsec         vs         am       gear       carb 
 17.848750   0.437500   0.406250   3.687500   2.812500 

Determine the type of column in flights dataset

glimpse(flights)
Rows: 336,776
Columns: 19
$ year           <int> 2013, 2013, 2013, 2013, 2013, 2013, 2013, 201…
$ month          <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
$ day            <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
$ dep_time       <int> 517, 533, 542, 544, 554, 554, 555, 557, 557, …
$ sched_dep_time <int> 515, 529, 540, 545, 600, 558, 600, 600, 600, …
$ dep_delay      <dbl> 2, 4, 2, -1, -6, -4, -5, -3, -3, -2, -2, -2, …
$ arr_time       <int> 830, 850, 923, 1004, 812, 740, 913, 709, 838,…
$ sched_arr_time <int> 819, 830, 850, 1022, 837, 728, 854, 723, 846,…
$ arr_delay      <dbl> 11, 20, 33, -18, -25, 12, 19, -14, -8, 8, -2,…
$ carrier        <chr> "UA", "UA", "AA", "B6", "DL", "UA", "B6", "EV…
$ flight         <int> 1545, 1714, 1141, 725, 461, 1696, 507, 5708, …
$ tailnum        <chr> "N14228", "N24211", "N619AA", "N804JB", "N668…
$ origin         <chr> "EWR", "LGA", "JFK", "JFK", "LGA", "EWR", "EW…
$ dest           <chr> "IAH", "IAH", "MIA", "BQN", "ATL", "ORD", "FL…
$ air_time       <dbl> 227, 227, 160, 183, 116, 150, 158, 53, 140, 1…
$ distance       <dbl> 1400, 1416, 1089, 1576, 762, 719, 1065, 229, …
$ hour           <dbl> 5, 5, 5, 5, 6, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, …
$ minute         <dbl> 15, 29, 40, 45, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0…
$ time_hour      <dttm> 2013-01-01 05:00:00, 2013-01-01 05:00:00, 20…
# find a function to determine type of column

typeof(flights$year)
[1] "integer"
flights %>% 
  map_chr(typeof)
          year          month            day       dep_time 
     "integer"      "integer"      "integer"      "integer" 
sched_dep_time      dep_delay       arr_time sched_arr_time 
     "integer"       "double"      "integer"      "integer" 
     arr_delay        carrier         flight        tailnum 
      "double"    "character"      "integer"    "character" 
        origin           dest       air_time       distance 
   "character"    "character"       "double"       "double" 
          hour         minute      time_hour 
      "double"       "double"       "double" 

Compute the number of unique values in each column of iris

glimpse(iris)
Rows: 150
Columns: 5
$ Sepal.Length <dbl> 5.1, 4.9, 4.7, 4.6, 5.0, 5.4, 4.6, 5.0, 4.4, 4.…
$ Sepal.Width  <dbl> 3.5, 3.0, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9, 3.…
$ Petal.Length <dbl> 1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5, 1.4, 1.…
$ Petal.Width  <dbl> 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.…
$ Species      <fct> setosa, setosa, setosa, setosa, setosa, setosa,…
iris %>% 
  map_int(n_distinct)
Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species 
          35           23           43           22            3 

Generate 10 random normals for each of miu = -10, 0, 10 and 100.

map(c(-10, 0, 10, 100), ~rnorm(n = 10, mean = .))
[[1]]
 [1]  -8.501952  -8.017926  -9.954449 -10.527896 -11.367753  -8.518719
 [7]  -8.973262 -10.295413  -8.666817 -10.657593

[[2]]
 [1]  1.0622306  0.1728670 -1.8079931  0.5542649  1.2390780  0.2565406
 [7]  0.3427404  1.8666900 -0.6743676 -1.1976806

[[3]]
 [1]  8.951252  9.671973  9.780482  9.520685  9.916101 10.088140
 [7]  9.475330 11.045631 10.755672  8.077710

[[4]]
 [1]  98.83447 100.34102 100.06690 100.40858 100.76098 101.69539
 [7]  99.91942 100.75977 100.04051 100.52748

How can you create a single vector that for each column in a data frame indicates whether or not it is a factor?

# function:
diamonds 
# A tibble: 53,940 x 10
   carat cut       color clarity depth table price     x     y     z
   <dbl> <ord>     <ord> <ord>   <dbl> <dbl> <int> <dbl> <dbl> <dbl>
 1  0.23 Ideal     E     SI2      61.5    55   326  3.95  3.98  2.43
 2  0.21 Premium   E     SI1      59.8    61   326  3.89  3.84  2.31
 3  0.23 Good      E     VS1      56.9    65   327  4.05  4.07  2.31
 4  0.29 Premium   I     VS2      62.4    58   334  4.2   4.23  2.63
 5  0.31 Good      J     SI2      63.3    58   335  4.34  4.35  2.75
 6  0.24 Very Good J     VVS2     62.8    57   336  3.94  3.96  2.48
 7  0.24 Very Good I     VVS1     62.3    57   336  3.95  3.98  2.47
 8  0.26 Very Good H     SI1      61.9    55   337  4.07  4.11  2.53
 9  0.22 Fair      E     VS2      65.1    61   337  3.87  3.78  2.49
10  0.23 Very Good H     VS1      59.4    61   338  4     4.05  2.39
# … with 53,930 more rows
is.factor(diamonds$color)
[1] TRUE
# to check if all the columns are factors:

diamonds %>% 
  map_lgl(is.factor)
  carat     cut   color clarity   depth   table   price       x 
  FALSE    TRUE    TRUE    TRUE   FALSE   FALSE   FALSE   FALSE 
      y       z 
  FALSE   FALSE 

Mapping over Multiple Arguments

use map2() or pmap()

Replicating worked example on Rebecca Barter’s website

Let me try to practice more using worked examples from http://www.rebeccabarter.com/blog/2019-08-19_purrr/.

# Create a function to add ten

add_ten <- function(x) {
  return(x + 10)
}

add_ten(10)
[1] 20
# Use it for map

numbers <- c(5,15,25)

numbers %>% 
  map_dbl(add_ten)
[1] 15 25 35
# if you want the object returned to be the same as the input:

numbers %>% 
  modify(add_ten)
[1] 15 25 35

Gapminder dataset

library(gapminder)

glimpse(gapminder)
Rows: 1,704
Columns: 6
$ country   <fct> "Afghanistan", "Afghanistan", "Afghanistan", "Afgh…
$ continent <fct> Asia, Asia, Asia, Asia, Asia, Asia, Asia, Asia, As…
$ year      <int> 1952, 1957, 1962, 1967, 1972, 1977, 1982, 1987, 19…
$ lifeExp   <dbl> 28.801, 30.332, 31.997, 34.020, 36.088, 38.438, 39…
$ pop       <int> 8425333, 9240934, 10267083, 11537966, 13079460, 14…
$ gdpPercap <dbl> 779.4453, 820.8530, 853.1007, 836.1971, 739.9811, …
# To identify the class of each column:

gapminder %>% 
  map_chr(class)
  country continent      year   lifeExp       pop gdpPercap 
 "factor"  "factor" "integer" "numeric" "integer" "numeric" 
# To identify the number of distinct values in the columnn:

gapminder %>% 
  map_dbl(n_distinct)
  country continent      year   lifeExp       pop gdpPercap 
      142         5        12      1626      1704      1704 

Tip:

First figure out what code to use for single element of the data frame. Then paste it into map_df()

# Extract single element (.x)
.x <- gapminder %>% 
  pluck(1) %>%  # to take first element of list ie country
  head()

.x
[1] Afghanistan Afghanistan Afghanistan Afghanistan Afghanistan
[6] Afghanistan
142 Levels: Afghanistan Albania Algeria Angola Argentina ... Zimbabwe
# Create code (.f)
data.frame(n_distinct(.x),
           class(.x))
  n_distinct..x. class..x.
1              1    factor
# Paste into code for map

gapminder %>% 
  map_df(~data.frame(n_distinct(.x),
           class(.x)),
         .id = "variable")
   variable n_distinct..x. class..x.
1   country            142    factor
2 continent              5    factor
3      year             12   integer
4   lifeExp           1626   numeric
5       pop           1704   integer
6 gdpPercap           1704   numeric

Maps with multiple input objects

map2(.x = object1, .y = object2, .f = function)

List columns and Nested Data Frames

gapminder_nested <- gapminder %>% 
  group_by(continent) %>% 
  nest()

gapminder_nested
# A tibble: 5 x 2
# Groups:   continent [5]
  continent data              
  <fct>     <list>            
1 Asia      <tibble [396 × 5]>
2 Europe    <tibble [360 × 5]>
3 Africa    <tibble [624 × 5]>
4 Americas  <tibble [300 × 5]>
5 Oceania   <tibble [24 × 5]> 
gapminder_nested %>% pluck("data", 1)
# A tibble: 396 x 5
   country      year lifeExp      pop gdpPercap
   <fct>       <int>   <dbl>    <int>     <dbl>
 1 Afghanistan  1952    28.8  8425333      779.
 2 Afghanistan  1957    30.3  9240934      821.
 3 Afghanistan  1962    32.0 10267083      853.
 4 Afghanistan  1967    34.0 11537966      836.
 5 Afghanistan  1972    36.1 13079460      740.
 6 Afghanistan  1977    38.4 14880372      786.
 7 Afghanistan  1982    39.9 12881816      978.
 8 Afghanistan  1987    40.8 13867957      852.
 9 Afghanistan  1992    41.7 16317921      649.
10 Afghanistan  1997    41.8 22227415      635.
# … with 386 more rows
# Calculate the average life expectancy within each continent and add it as a new column using mutate( ).

.x <- gapminder_nested %>% 
  pluck("data", 1)

.f <- mean(.x$lifeExp)
.f
[1] 60.0649
# put into map

gapminder_nested %>% 
  mutate(av_life_exp = map_dbl(data, 
                               ~mean(.x$lifeExp)))
# A tibble: 5 x 3
# Groups:   continent [5]
  continent data               av_life_exp
  <fct>     <list>                   <dbl>
1 Asia      <tibble [396 × 5]>        60.1
2 Europe    <tibble [360 × 5]>        71.9
3 Africa    <tibble [624 × 5]>        48.9
4 Americas  <tibble [300 × 5]>        64.7
5 Oceania   <tibble [24 × 5]>         74.3

Fitting a linear model separately for each continent

gapminder_nested <- gapminder_nested %>% 
  mutate(lm_obj = map(data, ~lm(lifeExp ~ pop + gdpPercap + year, data = .x)))

gapminder_nested
# A tibble: 5 x 3
# Groups:   continent [5]
  continent data               lm_obj
  <fct>     <list>             <list>
1 Asia      <tibble [396 × 5]> <lm>  
2 Europe    <tibble [360 × 5]> <lm>  
3 Africa    <tibble [624 × 5]> <lm>  
4 Americas  <tibble [300 × 5]> <lm>  
5 Oceania   <tibble [24 × 5]>  <lm>  
gapminder_nested %>% pluck("lm_obj", 1)

Call:
lm(formula = lifeExp ~ pop + gdpPercap + year, data = .x)

Coefficients:
(Intercept)          pop    gdpPercap         year  
 -7.833e+02    4.228e-11    2.510e-04    4.251e-01  
# predict the response for each continent

gapminder_nested <- gapminder_nested %>% 
  mutate(pred = map2(lm_obj,
                     data,
                     function(.lm, .data) predict(.lm, .data)))

gapminder_nested
# A tibble: 5 x 4
# Groups:   continent [5]
  continent data               lm_obj pred       
  <fct>     <list>             <list> <list>     
1 Asia      <tibble [396 × 5]> <lm>   <dbl [396]>
2 Europe    <tibble [360 × 5]> <lm>   <dbl [360]>
3 Africa    <tibble [624 × 5]> <lm>   <dbl [624]>
4 Americas  <tibble [300 × 5]> <lm>   <dbl [300]>
5 Oceania   <tibble [24 × 5]>  <lm>   <dbl [24]> 
# then calculate the correlation between observed and predicted response for each continent

gapminder_nested <- gapminder_nested %>% 
  mutate(cor = map2_dbl(pred,
                        data,
                        function(.pred, .data) cor(.pred, .data$lifeExp)))


gapminder_nested
# A tibble: 5 x 5
# Groups:   continent [5]
  continent data               lm_obj pred          cor
  <fct>     <list>             <list> <list>      <dbl>
1 Asia      <tibble [396 × 5]> <lm>   <dbl [396]> 0.723
2 Europe    <tibble [360 × 5]> <lm>   <dbl [360]> 0.834
3 Africa    <tibble [624 × 5]> <lm>   <dbl [624]> 0.645
4 Americas  <tibble [300 × 5]> <lm>   <dbl [300]> 0.779
5 Oceania   <tibble [24 × 5]>  <lm>   <dbl [24]>  0.987
# advanced exercise

gapminder %>% 
  group_by(continent) %>% 
  nest() %>% 
  mutate(lm_obj = map(data, ~lm(lifeExp ~ pop + year + gdpPercap, data = .))) %>% 
  mutate(lm_tidy = map(lm_obj, broom::tidy)) %>% 
  ungroup() %>% 
  transmute(continent, lm_tidy) %>%  # create new columns and dropping old
  unnest(cols = c(lm_tidy))
# A tibble: 20 x 6
   continent term         estimate std.error statistic  p.value
   <fct>     <chr>           <dbl>     <dbl>     <dbl>    <dbl>
 1 Asia      (Intercept) -7.83e+ 2   4.83e+1  -16.2    1.22e-45
 2 Asia      pop          4.23e-11   2.04e-9    0.0207 9.83e- 1
 3 Asia      year         4.25e- 1   2.44e-2   17.4    1.13e-50
 4 Asia      gdpPercap    2.51e- 4   3.01e-5    8.34   1.31e-15
 5 Europe    (Intercept) -1.61e+ 2   2.28e+1   -7.09   7.44e-12
 6 Europe    pop         -8.18e- 9   7.80e-9   -1.05   2.95e- 1
 7 Europe    year         1.16e- 1   1.16e-2    9.96   8.88e-21
 8 Europe    gdpPercap    3.25e- 4   2.15e-5   15.2    2.21e-40
 9 Africa    (Intercept) -4.70e+ 2   3.39e+1  -13.9    2.17e-38
10 Africa    pop         -3.68e- 9   1.89e-8   -0.195  8.45e- 1
11 Africa    year         2.61e- 1   1.71e-2   15.2    1.07e-44
12 Africa    gdpPercap    1.12e- 3   1.01e-4   11.1    2.46e-26
13 Americas  (Intercept) -5.33e+ 2   4.10e+1  -13.0    6.40e-31
14 Americas  pop         -2.15e- 8   8.62e-9   -2.49   1.32e- 2
15 Americas  year         3.00e- 1   2.08e-2   14.4    3.79e-36
16 Americas  gdpPercap    6.75e- 4   7.15e-5    9.44   1.13e-18
17 Oceania   (Intercept) -2.10e+ 2   5.12e+1   -4.10   5.61e- 4
18 Oceania   pop          8.37e- 9   3.34e-8    0.251  8.05e- 1
19 Oceania   year         1.42e- 1   2.65e-2    5.34   3.19e- 5
20 Oceania   gdpPercap    2.03e- 4   8.47e-5    2.39   2.66e- 2

Another tutorial from Jenny Bryan

The worked examples below are from: https://jennybc.github.io/purrr-tutorial/

library(purrr)
library(repurrrsive)
library(listviewer)

# this is a list
str(wesanderson)
List of 15
 $ GrandBudapest : chr [1:4] "#F1BB7B" "#FD6467" "#5B1A18" "#D67236"
 $ Moonrise1     : chr [1:4] "#F3DF6C" "#CEAB07" "#D5D5D3" "#24281A"
 $ Royal1        : chr [1:4] "#899DA4" "#C93312" "#FAEFD1" "#DC863B"
 $ Moonrise2     : chr [1:4] "#798E87" "#C27D38" "#CCC591" "#29211F"
 $ Cavalcanti    : chr [1:5] "#D8B70A" "#02401B" "#A2A475" "#81A88D" ...
 $ Royal2        : chr [1:5] "#9A8822" "#F5CDB4" "#F8AFA8" "#FDDDA0" ...
 $ GrandBudapest2: chr [1:4] "#E6A0C4" "#C6CDF7" "#D8A499" "#7294D4"
 $ Moonrise3     : chr [1:5] "#85D4E3" "#F4B5BD" "#9C964A" "#CDC08C" ...
 $ Chevalier     : chr [1:4] "#446455" "#FDD262" "#D3DDDC" "#C7B19C"
 $ Zissou        : chr [1:5] "#3B9AB2" "#78B7C5" "#EBCC2A" "#E1AF00" ...
 $ FantasticFox  : chr [1:5] "#DD8D29" "#E2D200" "#46ACC8" "#E58601" ...
 $ Darjeeling    : chr [1:5] "#FF0000" "#00A08A" "#F2AD00" "#F98400" ...
 $ Rushmore      : chr [1:5] "#E1BD6D" "#EABE94" "#0B775E" "#35274A" ...
 $ BottleRocket  : chr [1:7] "#A42820" "#5F5647" "#9B110E" "#3F5151" ...
 $ Darjeeling2   : chr [1:5] "#ECCBAE" "#046C9A" "#D69C4E" "#ABDDDE" ...
# use listviewer to view the list
jsonedit(wesanderson)
# list for Game of Thrones dataset
str(got_chars)
List of 30
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/1022"
  ..$ id         : int 1022
  ..$ name       : chr "Theon Greyjoy"
  ..$ gender     : chr "Male"
  ..$ culture    : chr "Ironborn"
  ..$ born       : chr "In 278 AC or 279 AC, at Pyke"
  ..$ died       : chr ""
  ..$ alive      : logi TRUE
  ..$ titles     : chr [1:3] "Prince of Winterfell" "Captain of Sea Bitch" "Lord of the Iron Islands (by law of the green lands)"
  ..$ aliases    : chr [1:4] "Prince of Fools" "Theon Turncloak" "Reek" "Theon Kinslayer"
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr ""
  ..$ allegiances: chr "House Greyjoy of Pyke"
  ..$ books      : chr [1:3] "A Game of Thrones" "A Storm of Swords" "A Feast for Crows"
  ..$ povBooks   : chr [1:2] "A Clash of Kings" "A Dance with Dragons"
  ..$ tvSeries   : chr [1:6] "Season 1" "Season 2" "Season 3" "Season 4" ...
  ..$ playedBy   : chr "Alfie Allen"
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/1052"
  ..$ id         : int 1052
  ..$ name       : chr "Tyrion Lannister"
  ..$ gender     : chr "Male"
  ..$ culture    : chr ""
  ..$ born       : chr "In 273 AC, at Casterly Rock"
  ..$ died       : chr ""
  ..$ alive      : logi TRUE
  ..$ titles     : chr [1:2] "Acting Hand of the King (former)" "Master of Coin (former)"
  ..$ aliases    : chr [1:11] "The Imp" "Halfman" "The boyman" "Giant of Lannister" ...
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr "https://www.anapioficeandfire.com/api/characters/2044"
  ..$ allegiances: chr "House Lannister of Casterly Rock"
  ..$ books      : chr [1:2] "A Feast for Crows" "The World of Ice and Fire"
  ..$ povBooks   : chr [1:4] "A Game of Thrones" "A Clash of Kings" "A Storm of Swords" "A Dance with Dragons"
  ..$ tvSeries   : chr [1:6] "Season 1" "Season 2" "Season 3" "Season 4" ...
  ..$ playedBy   : chr "Peter Dinklage"
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/1074"
  ..$ id         : int 1074
  ..$ name       : chr "Victarion Greyjoy"
  ..$ gender     : chr "Male"
  ..$ culture    : chr "Ironborn"
  ..$ born       : chr "In 268 AC or before, at Pyke"
  ..$ died       : chr ""
  ..$ alive      : logi TRUE
  ..$ titles     : chr [1:2] "Lord Captain of the Iron Fleet" "Master of the Iron Victory"
  ..$ aliases    : chr "The Iron Captain"
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr ""
  ..$ allegiances: chr "House Greyjoy of Pyke"
  ..$ books      : chr [1:3] "A Game of Thrones" "A Clash of Kings" "A Storm of Swords"
  ..$ povBooks   : chr [1:2] "A Feast for Crows" "A Dance with Dragons"
  ..$ tvSeries   : chr ""
  ..$ playedBy   : chr ""
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/1109"
  ..$ id         : int 1109
  ..$ name       : chr "Will"
  ..$ gender     : chr "Male"
  ..$ culture    : chr ""
  ..$ born       : chr ""
  ..$ died       : chr "In 297 AC, at Haunted Forest"
  ..$ alive      : logi FALSE
  ..$ titles     : chr ""
  ..$ aliases    : chr ""
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr ""
  ..$ allegiances: list()
  ..$ books      : chr "A Clash of Kings"
  ..$ povBooks   : chr "A Game of Thrones"
  ..$ tvSeries   : chr ""
  ..$ playedBy   : chr "Bronson Webb"
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/1166"
  ..$ id         : int 1166
  ..$ name       : chr "Areo Hotah"
  ..$ gender     : chr "Male"
  ..$ culture    : chr "Norvoshi"
  ..$ born       : chr "In 257 AC or before, at Norvos"
  ..$ died       : chr ""
  ..$ alive      : logi TRUE
  ..$ titles     : chr "Captain of the Guard at Sunspear"
  ..$ aliases    : chr ""
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr ""
  ..$ allegiances: chr "House Nymeros Martell of Sunspear"
  ..$ books      : chr [1:3] "A Game of Thrones" "A Clash of Kings" "A Storm of Swords"
  ..$ povBooks   : chr [1:2] "A Feast for Crows" "A Dance with Dragons"
  ..$ tvSeries   : chr [1:2] "Season 5" "Season 6"
  ..$ playedBy   : chr "DeObia Oparei"
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/1267"
  ..$ id         : int 1267
  ..$ name       : chr "Chett"
  ..$ gender     : chr "Male"
  ..$ culture    : chr ""
  ..$ born       : chr "At Hag's Mire"
  ..$ died       : chr "In 299 AC, at Fist of the First Men"
  ..$ alive      : logi FALSE
  ..$ titles     : chr ""
  ..$ aliases    : chr ""
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr ""
  ..$ allegiances: list()
  ..$ books      : chr [1:2] "A Game of Thrones" "A Clash of Kings"
  ..$ povBooks   : chr "A Storm of Swords"
  ..$ tvSeries   : chr ""
  ..$ playedBy   : chr ""
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/1295"
  ..$ id         : int 1295
  ..$ name       : chr "Cressen"
  ..$ gender     : chr "Male"
  ..$ culture    : chr ""
  ..$ born       : chr "In 219 AC or 220 AC"
  ..$ died       : chr "In 299 AC, at Dragonstone"
  ..$ alive      : logi FALSE
  ..$ titles     : chr "Maester"
  ..$ aliases    : chr ""
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr ""
  ..$ allegiances: list()
  ..$ books      : chr [1:2] "A Storm of Swords" "A Feast for Crows"
  ..$ povBooks   : chr "A Clash of Kings"
  ..$ tvSeries   : chr "Season 2"
  ..$ playedBy   : chr "Oliver Ford"
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/130"
  ..$ id         : int 130
  ..$ name       : chr "Arianne Martell"
  ..$ gender     : chr "Female"
  ..$ culture    : chr "Dornish"
  ..$ born       : chr "In 276 AC, at Sunspear"
  ..$ died       : chr ""
  ..$ alive      : logi TRUE
  ..$ titles     : chr "Princess of Dorne"
  ..$ aliases    : chr ""
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr ""
  ..$ allegiances: chr "House Nymeros Martell of Sunspear"
  ..$ books      : chr [1:4] "A Game of Thrones" "A Clash of Kings" "A Storm of Swords" "A Dance with Dragons"
  ..$ povBooks   : chr "A Feast for Crows"
  ..$ tvSeries   : chr ""
  ..$ playedBy   : chr ""
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/1303"
  ..$ id         : int 1303
  ..$ name       : chr "Daenerys Targaryen"
  ..$ gender     : chr "Female"
  ..$ culture    : chr "Valyrian"
  ..$ born       : chr "In 284 AC, at Dragonstone"
  ..$ died       : chr ""
  ..$ alive      : logi TRUE
  ..$ titles     : chr [1:5] "Queen of the Andals and the Rhoynar and the First Men, Lord of the Seven Kingdoms" "Khaleesi of the Great Grass Sea" "Breaker of Shackles/Chains" "Queen of Meereen" ...
  ..$ aliases    : chr [1:11] "Dany" "Daenerys Stormborn" "The Unburnt" "Mother of Dragons" ...
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr "https://www.anapioficeandfire.com/api/characters/1346"
  ..$ allegiances: chr "House Targaryen of King's Landing"
  ..$ books      : chr "A Feast for Crows"
  ..$ povBooks   : chr [1:4] "A Game of Thrones" "A Clash of Kings" "A Storm of Swords" "A Dance with Dragons"
  ..$ tvSeries   : chr [1:6] "Season 1" "Season 2" "Season 3" "Season 4" ...
  ..$ playedBy   : chr "Emilia Clarke"
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/1319"
  ..$ id         : int 1319
  ..$ name       : chr "Davos Seaworth"
  ..$ gender     : chr "Male"
  ..$ culture    : chr "Westeros"
  ..$ born       : chr "In 260 AC or before, at King's Landing"
  ..$ died       : chr ""
  ..$ alive      : logi TRUE
  ..$ titles     : chr [1:4] "Ser" "Lord of the Rainwood" "Admiral of the Narrow Sea" "Hand of the King"
  ..$ aliases    : chr [1:5] "Onion Knight" "Davos Shorthand" "Ser Onions" "Onion Lord" ...
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr "https://www.anapioficeandfire.com/api/characters/1676"
  ..$ allegiances: chr [1:2] "House Baratheon of Dragonstone" "House Seaworth of Cape Wrath"
  ..$ books      : chr "A Feast for Crows"
  ..$ povBooks   : chr [1:3] "A Clash of Kings" "A Storm of Swords" "A Dance with Dragons"
  ..$ tvSeries   : chr [1:5] "Season 2" "Season 3" "Season 4" "Season 5" ...
  ..$ playedBy   : chr "Liam Cunningham"
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/148"
  ..$ id         : int 148
  ..$ name       : chr "Arya Stark"
  ..$ gender     : chr "Female"
  ..$ culture    : chr "Northmen"
  ..$ born       : chr "In 289 AC, at Winterfell"
  ..$ died       : chr ""
  ..$ alive      : logi TRUE
  ..$ titles     : chr "Princess"
  ..$ aliases    : chr [1:16] "Arya Horseface" "Arya Underfoot" "Arry" "Lumpyface" ...
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr ""
  ..$ allegiances: chr "House Stark of Winterfell"
  ..$ books      : list()
  ..$ povBooks   : chr [1:5] "A Game of Thrones" "A Clash of Kings" "A Storm of Swords" "A Feast for Crows" ...
  ..$ tvSeries   : chr [1:6] "Season 1" "Season 2" "Season 3" "Season 4" ...
  ..$ playedBy   : chr "Maisie Williams"
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/149"
  ..$ id         : int 149
  ..$ name       : chr "Arys Oakheart"
  ..$ gender     : chr "Male"
  ..$ culture    : chr "Reach"
  ..$ born       : chr "At Old Oak"
  ..$ died       : chr "In 300 AC, at the Greenblood"
  ..$ alive      : logi FALSE
  ..$ titles     : chr "Ser"
  ..$ aliases    : chr ""
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr ""
  ..$ allegiances: chr "House Oakheart of Old Oak"
  ..$ books      : chr [1:4] "A Game of Thrones" "A Clash of Kings" "A Storm of Swords" "A Dance with Dragons"
  ..$ povBooks   : chr "A Feast for Crows"
  ..$ tvSeries   : chr ""
  ..$ playedBy   : chr ""
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/150"
  ..$ id         : int 150
  ..$ name       : chr "Asha Greyjoy"
  ..$ gender     : chr "Female"
  ..$ culture    : chr "Ironborn"
  ..$ born       : chr "In 275 AC or 276 AC, at Pyke"
  ..$ died       : chr ""
  ..$ alive      : logi TRUE
  ..$ titles     : chr [1:3] "Princess" "Captain of the Black Wind" "Conqueror of Deepwood Motte"
  ..$ aliases    : chr [1:2] "Esgred" "The Kraken's Daughter"
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr "https://www.anapioficeandfire.com/api/characters/1372"
  ..$ allegiances: chr [1:2] "House Greyjoy of Pyke" "House Ironmaker"
  ..$ books      : chr [1:2] "A Game of Thrones" "A Clash of Kings"
  ..$ povBooks   : chr [1:2] "A Feast for Crows" "A Dance with Dragons"
  ..$ tvSeries   : chr [1:3] "Season 2" "Season 3" "Season 4"
  ..$ playedBy   : chr "Gemma Whelan"
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/168"
  ..$ id         : int 168
  ..$ name       : chr "Barristan Selmy"
  ..$ gender     : chr "Male"
  ..$ culture    : chr "Westeros"
  ..$ born       : chr "In 237 AC"
  ..$ died       : chr ""
  ..$ alive      : logi TRUE
  ..$ titles     : chr [1:2] "Ser" "Hand of the Queen"
  ..$ aliases    : chr [1:5] "Barristan the Bold" "Arstan Whitebeard" "Ser Grandfather" "Barristan the Old" ...
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr ""
  ..$ allegiances: chr [1:2] "House Selmy of Harvest Hall" "House Targaryen of King's Landing"
  ..$ books      : chr [1:5] "A Game of Thrones" "A Clash of Kings" "A Storm of Swords" "A Feast for Crows" ...
  ..$ povBooks   : chr "A Dance with Dragons"
  ..$ tvSeries   : chr [1:4] "Season 1" "Season 3" "Season 4" "Season 5"
  ..$ playedBy   : chr "Ian McElhinney"
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/2066"
  ..$ id         : int 2066
  ..$ name       : chr "Varamyr"
  ..$ gender     : chr "Male"
  ..$ culture    : chr "Free Folk"
  ..$ born       : chr "At a village Beyond the Wall"
  ..$ died       : chr "In 300 AC, at a village Beyond the Wall"
  ..$ alive      : logi FALSE
  ..$ titles     : chr ""
  ..$ aliases    : chr [1:3] "Varamyr Sixskins" "Haggon" "Lump"
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr ""
  ..$ allegiances: list()
  ..$ books      : chr "A Storm of Swords"
  ..$ povBooks   : chr "A Dance with Dragons"
  ..$ tvSeries   : chr ""
  ..$ playedBy   : chr ""
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/208"
  ..$ id         : int 208
  ..$ name       : chr "Brandon Stark"
  ..$ gender     : chr "Male"
  ..$ culture    : chr "Northmen"
  ..$ born       : chr "In 290 AC, at Winterfell"
  ..$ died       : chr ""
  ..$ alive      : logi TRUE
  ..$ titles     : chr "Prince of Winterfell"
  ..$ aliases    : chr [1:3] "Bran" "Bran the Broken" "The Winged Wolf"
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr ""
  ..$ allegiances: chr "House Stark of Winterfell"
  ..$ books      : chr "A Feast for Crows"
  ..$ povBooks   : chr [1:4] "A Game of Thrones" "A Clash of Kings" "A Storm of Swords" "A Dance with Dragons"
  ..$ tvSeries   : chr [1:5] "Season 1" "Season 2" "Season 3" "Season 4" ...
  ..$ playedBy   : chr "Isaac Hempstead-Wright"
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/216"
  ..$ id         : int 216
  ..$ name       : chr "Brienne of Tarth"
  ..$ gender     : chr "Female"
  ..$ culture    : chr ""
  ..$ born       : chr "In 280 AC"
  ..$ died       : chr ""
  ..$ alive      : logi TRUE
  ..$ titles     : chr ""
  ..$ aliases    : chr [1:3] "The Maid of Tarth" "Brienne the Beauty" "Brienne the Blue"
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr ""
  ..$ allegiances: chr [1:3] "House Baratheon of Storm's End" "House Stark of Winterfell" "House Tarth of Evenfall Hall"
  ..$ books      : chr [1:3] "A Clash of Kings" "A Storm of Swords" "A Dance with Dragons"
  ..$ povBooks   : chr "A Feast for Crows"
  ..$ tvSeries   : chr [1:5] "Season 2" "Season 3" "Season 4" "Season 5" ...
  ..$ playedBy   : chr "Gwendoline Christie"
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/232"
  ..$ id         : int 232
  ..$ name       : chr "Catelyn Stark"
  ..$ gender     : chr "Female"
  ..$ culture    : chr "Rivermen"
  ..$ born       : chr "In 264 AC, at Riverrun"
  ..$ died       : chr "In 299 AC, at the Twins"
  ..$ alive      : logi FALSE
  ..$ titles     : chr "Lady of Winterfell"
  ..$ aliases    : chr [1:5] "Catelyn Tully" "Lady Stoneheart" "The Silent Sistet" "Mother Mercilesr" ...
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr "https://www.anapioficeandfire.com/api/characters/339"
  ..$ allegiances: chr [1:2] "House Stark of Winterfell" "House Tully of Riverrun"
  ..$ books      : chr [1:2] "A Feast for Crows" "A Dance with Dragons"
  ..$ povBooks   : chr [1:3] "A Game of Thrones" "A Clash of Kings" "A Storm of Swords"
  ..$ tvSeries   : chr [1:3] "Season 1" "Season 2" "Season 3"
  ..$ playedBy   : chr "Michelle Fairley"
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/238"
  ..$ id         : int 238
  ..$ name       : chr "Cersei Lannister"
  ..$ gender     : chr "Female"
  ..$ culture    : chr "Westerman"
  ..$ born       : chr "In 266 AC, at Casterly Rock"
  ..$ died       : chr ""
  ..$ alive      : logi TRUE
  ..$ titles     : chr [1:5] "Light of the West" "Queen Dowager" "Protector of the Realm" "Lady of Casterly Rock" ...
  ..$ aliases    : list()
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr "https://www.anapioficeandfire.com/api/characters/901"
  ..$ allegiances: chr "House Lannister of Casterly Rock"
  ..$ books      : chr [1:3] "A Game of Thrones" "A Clash of Kings" "A Storm of Swords"
  ..$ povBooks   : chr [1:2] "A Feast for Crows" "A Dance with Dragons"
  ..$ tvSeries   : chr [1:6] "Season 1" "Season 2" "Season 3" "Season 4" ...
  ..$ playedBy   : chr "Lena Headey"
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/339"
  ..$ id         : int 339
  ..$ name       : chr "Eddard Stark"
  ..$ gender     : chr "Male"
  ..$ culture    : chr "Northmen"
  ..$ born       : chr "In 263 AC, at Winterfell"
  ..$ died       : chr "In 299 AC, at Great Sept of Baelor in King's Landing"
  ..$ alive      : logi FALSE
  ..$ titles     : chr [1:5] "Lord of Winterfell" "Warden of the North" "Hand of the King" "Protector of the Realm" ...
  ..$ aliases    : chr [1:3] "Ned" "The Ned" "The Quiet Wolf"
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr "https://www.anapioficeandfire.com/api/characters/232"
  ..$ allegiances: chr "House Stark of Winterfell"
  ..$ books      : chr [1:5] "A Clash of Kings" "A Storm of Swords" "A Feast for Crows" "A Dance with Dragons" ...
  ..$ povBooks   : chr "A Game of Thrones"
  ..$ tvSeries   : chr [1:2] "Season 1" "Season 6"
  ..$ playedBy   : chr [1:3] "Sean Bean" "Sebastian Croft" "Robert Aramayo"
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/529"
  ..$ id         : int 529
  ..$ name       : chr "Jaime Lannister"
  ..$ gender     : chr "Male"
  ..$ culture    : chr "Westerlands"
  ..$ born       : chr "In 266 AC, at Casterly Rock"
  ..$ died       : chr ""
  ..$ alive      : logi TRUE
  ..$ titles     : chr [1:3] "Ser" "Lord Commander of the Kingsguard" "Warden of the East (formerly)"
  ..$ aliases    : chr [1:4] "The Kingslayer" "The Lion of Lannister" "The Young Lion" "Cripple"
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr ""
  ..$ allegiances: chr "House Lannister of Casterly Rock"
  ..$ books      : chr [1:2] "A Game of Thrones" "A Clash of Kings"
  ..$ povBooks   : chr [1:3] "A Storm of Swords" "A Feast for Crows" "A Dance with Dragons"
  ..$ tvSeries   : chr [1:5] "Season 1" "Season 2" "Season 3" "Season 4" ...
  ..$ playedBy   : chr "Nikolaj Coster-Waldau"
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/576"
  ..$ id         : int 576
  ..$ name       : chr "Jon Connington"
  ..$ gender     : chr "Male"
  ..$ culture    : chr "Stormlands"
  ..$ born       : chr "In or between 263 AC and 265 AC"
  ..$ died       : chr ""
  ..$ alive      : logi TRUE
  ..$ titles     : chr [1:3] "Lord of Griffin's Roost" "Hand of the King" "Hand of the True King"
  ..$ aliases    : chr "Griffthe Mad King's Hand"
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr ""
  ..$ allegiances: chr [1:2] "House Connington of Griffin's Roost" "House Targaryen of King's Landing"
  ..$ books      : chr [1:3] "A Storm of Swords" "A Feast for Crows" "The World of Ice and Fire"
  ..$ povBooks   : chr "A Dance with Dragons"
  ..$ tvSeries   : chr ""
  ..$ playedBy   : chr ""
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/583"
  ..$ id         : int 583
  ..$ name       : chr "Jon Snow"
  ..$ gender     : chr "Male"
  ..$ culture    : chr "Northmen"
  ..$ born       : chr "In 283 AC"
  ..$ died       : chr ""
  ..$ alive      : logi TRUE
  ..$ titles     : chr "Lord Commander of the Night's Watch"
  ..$ aliases    : chr [1:8] "Lord Snow" "Ned Stark's Bastard" "The Snow of Winterfell" "The Crow-Come-Over" ...
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr ""
  ..$ allegiances: chr "House Stark of Winterfell"
  ..$ books      : chr "A Feast for Crows"
  ..$ povBooks   : chr [1:4] "A Game of Thrones" "A Clash of Kings" "A Storm of Swords" "A Dance with Dragons"
  ..$ tvSeries   : chr [1:6] "Season 1" "Season 2" "Season 3" "Season 4" ...
  ..$ playedBy   : chr "Kit Harington"
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/60"
  ..$ id         : int 60
  ..$ name       : chr "Aeron Greyjoy"
  ..$ gender     : chr "Male"
  ..$ culture    : chr "Ironborn"
  ..$ born       : chr "In or between 269 AC and 273 AC, at Pyke"
  ..$ died       : chr ""
  ..$ alive      : logi TRUE
  ..$ titles     : chr [1:2] "Priest of the Drowned God" "Captain of the Golden Storm (formerly)"
  ..$ aliases    : chr [1:2] "The Damphair" "Aeron Damphair"
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr ""
  ..$ allegiances: chr "House Greyjoy of Pyke"
  ..$ books      : chr [1:4] "A Game of Thrones" "A Clash of Kings" "A Storm of Swords" "A Dance with Dragons"
  ..$ povBooks   : chr "A Feast for Crows"
  ..$ tvSeries   : chr "Season 6"
  ..$ playedBy   : chr "Michael Feast"
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/605"
  ..$ id         : int 605
  ..$ name       : chr "Kevan Lannister"
  ..$ gender     : chr "Male"
  ..$ culture    : chr ""
  ..$ born       : chr "In 244 AC"
  ..$ died       : chr "In 300 AC, at King's Landing"
  ..$ alive      : logi FALSE
  ..$ titles     : chr [1:4] "Ser" "Master of laws" "Lord Regent" "Protector of the Realm"
  ..$ aliases    : chr ""
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr "https://www.anapioficeandfire.com/api/characters/327"
  ..$ allegiances: chr "House Lannister of Casterly Rock"
  ..$ books      : chr [1:4] "A Game of Thrones" "A Clash of Kings" "A Storm of Swords" "A Feast for Crows"
  ..$ povBooks   : chr "A Dance with Dragons"
  ..$ tvSeries   : chr [1:4] "Season 1" "Season 2" "Season 5" "Season 6"
  ..$ playedBy   : chr "Ian Gelder"
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/743"
  ..$ id         : int 743
  ..$ name       : chr "Melisandre"
  ..$ gender     : chr "Female"
  ..$ culture    : chr "Asshai"
  ..$ born       : chr "At Unknown"
  ..$ died       : chr ""
  ..$ alive      : logi TRUE
  ..$ titles     : chr ""
  ..$ aliases    : chr [1:5] "The Red Priestess" "The Red Woman" "The King's Red Shadow" "Lady Red" ...
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr ""
  ..$ allegiances: list()
  ..$ books      : chr [1:3] "A Clash of Kings" "A Storm of Swords" "A Feast for Crows"
  ..$ povBooks   : chr "A Dance with Dragons"
  ..$ tvSeries   : chr [1:5] "Season 2" "Season 3" "Season 4" "Season 5" ...
  ..$ playedBy   : chr "Carice van Houten"
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/751"
  ..$ id         : int 751
  ..$ name       : chr "Merrett Frey"
  ..$ gender     : chr "Male"
  ..$ culture    : chr "Rivermen"
  ..$ born       : chr "In 262 AC"
  ..$ died       : chr "In 300 AC, at Near Oldstones"
  ..$ alive      : logi FALSE
  ..$ titles     : chr ""
  ..$ aliases    : chr "Merrett Muttonhead"
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr "https://www.anapioficeandfire.com/api/characters/712"
  ..$ allegiances: chr "House Frey of the Crossing"
  ..$ books      : chr [1:4] "A Game of Thrones" "A Clash of Kings" "A Feast for Crows" "A Dance with Dragons"
  ..$ povBooks   : chr "A Storm of Swords"
  ..$ tvSeries   : chr ""
  ..$ playedBy   : chr ""
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/844"
  ..$ id         : int 844
  ..$ name       : chr "Quentyn Martell"
  ..$ gender     : chr "Male"
  ..$ culture    : chr "Dornish"
  ..$ born       : chr "In 281 AC, at Sunspear, Dorne"
  ..$ died       : chr "In 300 AC, at Meereen"
  ..$ alive      : logi FALSE
  ..$ titles     : chr "Prince"
  ..$ aliases    : chr [1:4] "Frog" "Prince Frog" "The prince who came too late" "The Dragonrider"
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr ""
  ..$ allegiances: chr "House Nymeros Martell of Sunspear"
  ..$ books      : chr [1:4] "A Game of Thrones" "A Clash of Kings" "A Storm of Swords" "A Feast for Crows"
  ..$ povBooks   : chr "A Dance with Dragons"
  ..$ tvSeries   : chr ""
  ..$ playedBy   : chr ""
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/954"
  ..$ id         : int 954
  ..$ name       : chr "Samwell Tarly"
  ..$ gender     : chr "Male"
  ..$ culture    : chr "Andal"
  ..$ born       : chr "In 283 AC, at Horn Hill"
  ..$ died       : chr ""
  ..$ alive      : logi TRUE
  ..$ titles     : chr ""
  ..$ aliases    : chr [1:7] "Sam" "Ser Piggy" "Prince Pork-chop" "Lady Piggy" ...
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr ""
  ..$ allegiances: chr "House Tarly of Horn Hill"
  ..$ books      : chr [1:3] "A Game of Thrones" "A Clash of Kings" "A Dance with Dragons"
  ..$ povBooks   : chr [1:2] "A Storm of Swords" "A Feast for Crows"
  ..$ tvSeries   : chr [1:6] "Season 1" "Season 2" "Season 3" "Season 4" ...
  ..$ playedBy   : chr "John Bradley-West"
 $ :List of 18
  ..$ url        : chr "https://www.anapioficeandfire.com/api/characters/957"
  ..$ id         : int 957
  ..$ name       : chr "Sansa Stark"
  ..$ gender     : chr "Female"
  ..$ culture    : chr "Northmen"
  ..$ born       : chr "In 286 AC, at Winterfell"
  ..$ died       : chr ""
  ..$ alive      : logi TRUE
  ..$ titles     : chr "Princess"
  ..$ aliases    : chr [1:3] "Little bird" "Alayne Stone" "Jonquil"
  ..$ father     : chr ""
  ..$ mother     : chr ""
  ..$ spouse     : chr "https://www.anapioficeandfire.com/api/characters/1052"
  ..$ allegiances: chr [1:2] "House Baelish of Harrenhal" "House Stark of Winterfell"
  ..$ books      : chr "A Dance with Dragons"
  ..$ povBooks   : chr [1:4] "A Game of Thrones" "A Clash of Kings" "A Storm of Swords" "A Feast for Crows"
  ..$ tvSeries   : chr [1:6] "Season 1" "Season 2" "Season 3" "Season 4" ...
  ..$ playedBy   : chr "Sophie Turner"
jsonedit(got_chars)
# Who are the GoT characters?

got_chars %>% 
  map_chr("name") # to retrieve the elements with name
 [1] "Theon Greyjoy"      "Tyrion Lannister"   "Victarion Greyjoy" 
 [4] "Will"               "Areo Hotah"         "Chett"             
 [7] "Cressen"            "Arianne Martell"    "Daenerys Targaryen"
[10] "Davos Seaworth"     "Arya Stark"         "Arys Oakheart"     
[13] "Asha Greyjoy"       "Barristan Selmy"    "Varamyr"           
[16] "Brandon Stark"      "Brienne of Tarth"   "Catelyn Stark"     
[19] "Cersei Lannister"   "Eddard Stark"       "Jaime Lannister"   
[22] "Jon Connington"     "Jon Snow"           "Aeron Greyjoy"     
[25] "Kevan Lannister"    "Melisandre"         "Merrett Frey"      
[28] "Quentyn Martell"    "Samwell Tarly"      "Sansa Stark"       

Learning points

I think I am still swimming in this package.. The basic idea of using the map functions is to try it on one element and then map it, but I think I need more practice…

Reference

https://r4ds.had.co.nz/

https://jrnold.github.io/r4ds-exercise-solutions/

https://www.r-bloggers.com/2015/12/how-to-write-the-first-for-loop-in-r/

http://www.rebeccabarter.com/blog/2019-08-19_purrr/

https://jennybc.github.io/purrr-tutorial/

Citation

For attribution, please cite this work as

lruolin (2021, May 27). pRactice corner: Iteration with purrr. Retrieved from https://lruolin.github.io/myBlog/posts/20210526_Tidyverse Chap 17 - Iteration with purrr/

BibTeX citation

@misc{lruolin2021iteration,
  author = {lruolin, },
  title = {pRactice corner: Iteration with purrr},
  url = {https://lruolin.github.io/myBlog/posts/20210526_Tidyverse Chap 17 - Iteration with purrr/},
  year = {2021}
}